package org.foreningsgatan.modules.glcore.graphics;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.imageio.ImageIO;

import org.foreningsgatan.modular.common.logging.Log;

public class PackedTextureLoader {
	private Map<BufferedImage, PackedTexture> toBePacked;
	
	private Log log = new Log(this.getClass());

	private TexturePacker currentPacker;

	private List<PackedTexture> currentlyPacked;
	
	public PackedTextureLoader() {
		toBePacked = new HashMap<BufferedImage, PackedTexture>();
	}
	
	public PackedTexture add(File vFile) throws IOException {
		return add(ImageIO.read(vFile));
	}
	
	public PackedTexture add(InputStream is, String fileSuffix) throws IOException {
		return add(ImageIO.read(is));
	}
	
	public PackedTexture add(BufferedImage image) {
		PackedTexture packedTexture = new PackedTexture();
		
		toBePacked.put(image, packedTexture);
		
		return packedTexture;
	}
	
	private void finalizeTexturePacker(TextureManager tm) throws IOException {
		long id = tm.loadTexture(currentPacker.getResult());
		
		for (PackedTexture packedTexture: currentlyPacked) {
			packedTexture.packedTextureId = id;
		}
		
		log.debug("Packed texture %s contains %s texture", id, currentlyPacked.size());
	}
	
	public void pack(TextureManager tm) throws IOException {
		log.debug("Packing textures ..");
		
		currentPacker = new TexturePacker();
		currentlyPacked = new LinkedList<PackedTexture>();
		
		for (Entry<BufferedImage, PackedTexture> entry: toBePacked.entrySet()) {
			PackedTexture currentPackedTexture = entry.getValue();
			
			if (!currentPacker.hasRoom(entry.getKey())) {
				finalizeTexturePacker(tm);
				
				currentPacker = new TexturePacker();
				currentlyPacked.clear();
			}
			
			currentPackedTexture.bounds = currentPacker.add(entry.getKey());
			currentlyPacked.add(currentPackedTexture);
		}
		
		finalizeTexturePacker(tm);
		
		log.debug("Done");
	}
}
